#version 430 core

#define LOC_X 16
#define LOC_Y 16

#define GRID_SIZE_X 64
#define GRID_SIZE_Y 64
#define UNIT_OFFSET_X 1.f/(GRID_SIZE_X+1)
#define UNIT_OFFSET_Y 1.f/(GRID_SIZE_Y+1)

layout(local_size_x=LOC_X, local_size_y=LOC_Y) in;

layout(binding=0) uniform sampler2D jumpFloodingSrc;
layout(binding=0, rgba32f) uniform writeonly image2D jumpFloodingDst;

uniform uvec2 k;

void main(void)
{
	ivec2 gid = ivec2(gl_GlobalInvocationID.xy);
	if (gid.x <= GRID_SIZE_X && gid.y <= GRID_SIZE_Y)
	{
		vec2 center = (vec2(gid)+vec2(0.5f,0.5f)) * vec2(UNIT_OFFSET_X, UNIT_OFFSET_Y);
		vec3 lookupBest = texture(jumpFloodingSrc, center).xyz; // x is squared shortest found distance, yz is position (in integers 0-GRID_SIZE)

		vec2 offsetTexCoords = k*vec2(UNIT_OFFSET_X, UNIT_OFFSET_Y);
		for (int y=-1; y<=1; y++)
		{
			for (int x=-1; x<=1; x++)
			{
				if (!(x==0 && y==0))
				{
					vec3 lookupOffset = texture(jumpFloodingSrc, center + vec2(x,y)*offsetTexCoords).xyz;
					vec2 centerToOffset = gid-lookupOffset.yz;
					float distSq = dot(centerToOffset, centerToOffset);
					lookupBest = mix(lookupBest, vec3(distSq, lookupOffset.yz), distSq < lookupBest.x);
				}
			}
		}

		imageStore(jumpFloodingDst, gid, vec4(lookupBest, 1.f));
	}
}